/*类 */
class Person {
  name: string;
  getName():void{
    console.log(this.name);
  }
}

// Person是实例的类型
let p1:Person = new Person();
p1.name = 'gc';
p1.getName();

//存取器
class User{
  // myName: string=''
  constructor(public myName:string){
    // this.myName = myName
  }
  get name(){
    return this.myName;
  }
  set name(val){
    this.myName = val.toUpperCase();
  }
}
let user = new User('ggcc');
// user.name = 'gg';
console.log(user);

class Father{
  static className = 'father';
  public name:string;
  protected age:number; //只有自己类，本身和子类能访问
  private money:number; //只能被本身访问
  constructor(name:string,age:number,money:number){
    this.name = name;
    this.age = age;
    this.money = money;
  }
  getName(){
    console.log(this.name)
  }
  getAge(){
    console.log(this.age)
  }
  getMoney(){
    console.log(this.money);
  }
}
class Child extends Father{
  constructor(name:string,age:number,money:number){
    super(name,age,money);
  }
  getParentAge(){
    console.log(this.age);
  }
}

let child = new Child('zz',22,100);
child.getMoney();
child.name;
child.getAge();
Child.className;
// child.age;
// child.money;

//装饰器： https://www.cnblogs.com/mengff/p/9661648.html
//类装饰器 装饰类的 用在类声明之前，用来监视、修改和替换类的定义
//nest.js大量用到装饰器
namespace cc {
  function enhancer(name:string){
    return function enhancer(target:Function){
      target.prototype.name = name;
      target.prototype.eat = function(){
        console.log(this.name,'eat');
      }
   }
  }
 
  @enhancer('gu')
  class Person {
   
  }
  let p:any = new Person();
  p.name;
  p.eat();
}


//属性装饰器
namespace c {
  /**
   * 属性装饰器有两个参数
   * @param target 如果是静态成员，target就是类的构造函数，如果是实例成员就是类的原型对象
   * @param property 方法或者属性名称
   */
  function upperCase(target:any,property:string){
      let value = target[property];
      const getter = ()=> value;
      const setter = (newVal:string) => {
        value = newVal.toUpperCase();
      };
      if(delete target[property]){
        Object.defineProperty(target,property,{
           get: getter,
           set: setter,
           enumerable: true,
           configurable: true
        })
      }                                           
  }
  class Person {
    @upperCase
    name:string='cc'
  } 
  let p = new Person();
  p.name = 'zz';
  console.log(p.name);
}

//参数装饰器
namespace d {
  function addAge(target:any,methodName:string,paramsIndex:number){
    console.log(target,methodName,paramsIndex);
  }
  class Person {
    login(username:string,@addAge password:string){
      console.log(username,password);
    }
  }
}

/**
 * 装饰器的执行顺序
 * 有多个装饰器的时候，从最后一个参数依次向前执行
 * 方法和方法参数中，参数装饰器先执行
 * 类装饰器总是最后执行
 * 方法和属性装饰器，谁在前面先执行，因为参数是属于方法的一部分，所以参数会紧贴着方法执行
 * 不同类别从上往下，同一类别从下往上，类总是最后的
*/
namespace e {
  function classDecorator1(){
    return function(target:any){
      console.log('class1');
    }
  }
  function classDecorator2(){
    return function(target:any){
      console.log('class2');
    }
  }

  @classDecorator1()
  @classDecorator2() //先执行这个 再执行1
  class Person {
    
  }
}

